AWS Lambda のレスポンスストリーミングを使って API Gateway + Lambda 構成で 10 MB のレスポンスを生成してみた
いわさです。
先日のアップデートで Lambda の関数 URL を使う場合は関数がレスポンスを返す方法としてレスポンスストリーミングが使えるようになりました。
従来は Lambda のレスポンスには 6 MB の制限が存在しており、API Gateway (REST) の 10 MB よりも統合される Lambda のほうが上限が低いこともあって注意しなければならない点でした。
しかし、レスポンスストリーミングによってレスポンスサイズの上限が緩和されるので、API Gateway を使う時にレスポンスサイズ上限まで活用したい場合、利用出来るかもしれません。
今回は S3 バケットに大きなファイルサイズのオブジェクトをアップロードし、API Gateway や Lambda 経由で GET してみましたので検証結果を紹介します。
Amazon S3 バケットには次のように 4 MB、9 MB、11 MB のダミーファイルをアップロードしておきます。
% ls -lh total 49152 -rw-r--r-- 1 iwasa.takahito staff 4.0M Apr 24 07:44 hoge1 -rw-r--r-- 1 iwasa.takahito staff 9.0M Apr 24 07:44 hoge2 -rw-r--r-- 1 iwasa.takahito staff 11M Apr 24 07:44 hoge3 % shasum -a 256 hoge1 bb9f8df61474d25e71fa00722318cd387396ca1736605e1248821cc0de3d3af8 hoge1 % shasum -a 256 hoge2 d2ee4703cd9698945ca7b9fe1689ea3095597eac1a0afd8dba00cac7894fdc43 hoge2 % shasum -a 256 hoge3 d4d2639ad94b0211839461226eb57a5e185829e5c4a9783c2da9f0a3da032bf5 hoge3
後続の確認用にハッシュを計算しておきましょう。
Amazon S3 の静的ウェブサイトホスティング機能を使った場合
まずは先程の Amazon S3 バケットの静的ウェブサイトホスティング機能を有効化して直接エンドポイントへアクセスしてみます。
次のようなイメージです。
cURL を使ってリクエストを送信します。
% curl http://iwasa-hoge-public-bucket.s3-website-ap-northeast-1.amazonaws.com/hoge0424/hoge1 -o hoge1s3 % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 4096k 100 4096k 0 0 7877k 0 --:--:-- --:--:-- --:--:-- 7984k % curl http://iwasa-hoge-public-bucket.s3-website-ap-northeast-1.amazonaws.com/hoge0424/hoge2 -o hoge2s3 % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 9216k 100 9216k 0 0 12.8M 0 --:--:-- --:--:-- --:--:-- 12.9M % curl http://iwasa-hoge-public-bucket.s3-website-ap-northeast-1.amazonaws.com/hoge0424/hoge3 -o hoge3s3 % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 11.0M 100 11.0M 0 0 14.5M 0 --:--:-- --:--:-- --:--:-- 14.6M % shasum -a 256 hoge1s3 bb9f8df61474d25e71fa00722318cd387396ca1736605e1248821cc0de3d3af8 hoge1s3 % shasum -a 256 hoge2s3 d2ee4703cd9698945ca7b9fe1689ea3095597eac1a0afd8dba00cac7894fdc43 hoge2s3 % shasum -a 256 hoge3s3 d4d2639ad94b0211839461226eb57a5e185829e5c4a9783c2da9f0a3da032bf5 hoge3s3
全てのファイルを取得することが出来ました。
ハッシュも一致しているので問題なくダウンロード出来ていますね。
API Gateway + S3 (HTTP Proxy)
続いて S3 静的ウェブサイトホスティングに対して HTTP プロキシ統合で API Gatway を前段に配置してみましょう。
次のようなイメージです。
API Gateway の構成ではプロキシリソースで S3 のエンドポイント URL を設定しています。
先程と同じように cURL でアクセスしてみます。
期待する動作としては API Gateway のペイロードサイズ上限 10 MB 以上の挙動が確認出来ると良い感じですが、はたして。
% curl https://nbnhq77404.execute-api.ap-northeast-1.amazonaws.com/hoge/s3/hoge1 -o hoge1 % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 4096k 100 4096k 0 0 4872k 0 --:--:-- --:--:-- --:--:-- 4911k % curl https://nbnhq77404.execute-api.ap-northeast-1.amazonaws.com/hoge/s3/hoge2 -o hoge2 % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 9216k 100 9216k 0 0 8615k 0 0:00:01 0:00:01 --:--:-- 8645k % curl https://nbnhq77404.execute-api.ap-northeast-1.amazonaws.com/hoge/s3/hoge3 -o hoge3 % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 36 100 36 0 0 82 0 --:--:-- --:--:-- --:--:-- 83 % shasum -a 256 hoge1 bb9f8df61474d25e71fa00722318cd387396ca1736605e1248821cc0de3d3af8 hoge1 % shasum -a 256 hoge2 d2ee4703cd9698945ca7b9fe1689ea3095597eac1a0afd8dba00cac7894fdc43 hoge2 % shasum -a 256 hoge3 660f19c09a36ca1620054261590b73df388b95892469ff17c1caf4e50376aa02 hoge3 % curl -i https://nbnhq77404.execute-api.ap-northeast-1.amazonaws.com/hoge/s3/hoge3 HTTP/2 500 date: Sun, 23 Apr 2023 23:01:37 GMT content-type: application/json content-length: 36 x-amzn-requestid: c1c4007c-e44b-4a76-9a07-dd3a606179a0 x-amzn-errortype: InternalServerErrorException x-amz-apigw-id: D2nQ0FcZtjMF6pA= {"message": "Internal server error"}
11 MB のオブジェクト hoge3 は ステータスが 500 になりました。
Internal server error
が発生していますね。
Lambda 関数 URL + S3
続いては API Gateway ではなく、Lambda をプロキシとして S3 静的ウェブサイトホスティングへアクセスしてみます。
次のような構成です。
レスポンス形式ではデフォルト(BUFFERED)と、先日のアップデートのもの(RESPONSE_STREAM)のどちらも試してみたいと思います。
デフォルト
以下を参考に HTTP クライアントで S3 からオブジェクトをダウンロードする Lambda 関数を作成しました。
import { get } from 'http'; export const handler = async (event) => { return new Promise((resolve, reject) => { const url = 'http://iwasa-hoge-public-bucket.s3-website-ap-northeast-1.amazonaws.com/hoge0424' + event.rawPath; console.info(url); const request = get(url, (res) => { const chunks = []; res.on('data', (chunk) => { chunks.push(chunk); }); res.on('end', () => { const data = Buffer.concat(chunks); resolve({ statusCode: 200, headers: { 'Content-Type': res.headers['content-type'] }, isBase64Encoded: true, body: data.toString('base64') }); }); }); request.on('error', (error) => { console.error('Error fetching data:', error); resolve({ statusCode: 500, body: JSON.stringify({ message: 'Error fetching data' }) }); }); }); };
関数 URL を作成し、cURL でリクエストを送信してみます。
% curl -i https://qycq7nmrsmgvnwhwkhxbcpkyhm0angxc.lambda-url.ap-northeast-1.on.aws/hoge1 HTTP/1.1 200 OK Date: Mon, 24 Apr 2023 12:34:50 GMT Content-Type: binary/octet-stream Content-Length: 4194304 Connection: keep-alive x-amzn-RequestId: 3e3d2cb6-44ef-4920-a923-2d4a681e32dc X-Amzn-Trace-Id: root=1-64467769-09e36838178ff19951483176;sampled=0;lineage=12846133:0 Warning: Binary output can mess up your terminal. Use "--output -" to tell Warning: curl to output it to your terminal anyway, or consider "--output Warning: <FILE>" to save to a file. % curl -i https://qycq7nmrsmgvnwhwkhxbcpkyhm0angxc.lambda-url.ap-northeast-1.on.aws/hoge2 HTTP/1.1 502 Bad Gateway Date: Mon, 24 Apr 2023 12:34:38 GMT Content-Type: application/json Content-Length: 21 Connection: keep-alive x-amzn-RequestId: 798d59e0-47ba-4160-b916-692b5e5709b5 X-Amzn-Trace-Id: root=1-6446775b-5ad2b6885da31ddd714b036f;sampled=0;lineage=12846133:0 Internal Server Error % curl -i https://qycq7nmrsmgvnwhwkhxbcpkyhm0angxc.lambda-url.ap-northeast-1.on.aws/hoge3 HTTP/1.1 502 Bad Gateway Date: Mon, 24 Apr 2023 12:34:46 GMT Content-Type: application/json Content-Length: 21 Connection: keep-alive x-amzn-RequestId: cce5340e-50ee-4b25-9331-6d43813ac7a0 X-Amzn-Trace-Id: root=1-64467763-21a790d86ee99c88426e426c;sampled=0;lineage=12846133:0 Internal Server Error
4 MB のオブジェクトへのアクセスのみ成功しました。
9 MB と 11 MB は失敗しました。
仕様どおり 6 MB の壁がありますね。
レスポンスストリーミング
続いて先程のコードを少し修正し、レスポンスストリーミング形式で返却するようにします。
ざっくりいうとawslambda.streamifyResponse
でラップしてやって、responseStream
オブジェクトを使って都度送信するように変更しています。
import { get } from 'http'; export const handler = awslambda.streamifyResponse( async (event, responseStream, context) => { return new Promise((resolve, reject) => { const url = 'http://iwasa-hoge-public-bucket.s3-website-ap-northeast-1.amazonaws.com/hoge0424' + event.rawPath; console.info(url); const request = get(url, (res) => { const chunks = []; res.on('data', (chunk) => { responseStream.write(chunk); }); res.on('end', () => { responseStream.end(); }); }); request.on('error', (error) => { console.error('Error fetching data:', error); resolve({ statusCode: 500, body: JSON.stringify({ message: 'Error fetching data' }) }); }); }); } );
cURL でアクセスしてみましょう。
% curl http://iwasa-hoge-public-bucket.s3-website-ap-northeast-1.amazonaws.com/hoge0424/hoge1 -o hoge1a % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 4096k 100 4096k 0 0 3993k 0 0:00:01 0:00:01 --:--:-- 4019k % curl http://iwasa-hoge-public-bucket.s3-website-ap-northeast-1.amazonaws.com/hoge0424/hoge2 -o hoge2a % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 9216k 100 9216k 0 0 7247k 0 0:00:01 0:00:01 --:--:-- 7279k % curl http://iwasa-hoge-public-bucket.s3-website-ap-northeast-1.amazonaws.com/hoge0424/hoge3 -o hoge3a % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 11.0M 100 11.0M 0 0 7420k 0 0:00:01 0:00:01 --:--:-- 7439k % curl https://rn3cg3rnzukafz7jisje7ysbay0wtdjv.lambda-url.ap-northeast-1.on.aws/hoge1 -o hoge1b % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 4096k 0 4096k 0 0 1213k 0 --:--:-- 0:00:03 --:--:-- 1216k % curl https://rn3cg3rnzukafz7jisje7ysbay0wtdjv.lambda-url.ap-northeast-1.on.aws/hoge2 -o hoge2b % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 9216k 0 9216k 0 0 2738k 0 --:--:-- 0:00:03 --:--:-- 2744k % curl https://rn3cg3rnzukafz7jisje7ysbay0wtdjv.lambda-url.ap-northeast-1.on.aws/hoge3 -o hoge3b % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 11.0M 0 11.0M 0 0 3514k 0 --:--:-- 0:00:03 --:--:-- 3521k % shasum -a 256 hoge1a bb9f8df61474d25e71fa00722318cd387396ca1736605e1248821cc0de3d3af8 hoge1a % shasum -a 256 hoge1b bb9f8df61474d25e71fa00722318cd387396ca1736605e1248821cc0de3d3af8 hoge1b % shasum -a 256 hoge2a d2ee4703cd9698945ca7b9fe1689ea3095597eac1a0afd8dba00cac7894fdc43 hoge2a % shasum -a 256 hoge2b d2ee4703cd9698945ca7b9fe1689ea3095597eac1a0afd8dba00cac7894fdc43 hoge2b % shasum -a 256 hoge3a d4d2639ad94b0211839461226eb57a5e185829e5c4a9783c2da9f0a3da032bf5 hoge3a % shasum -a 256 hoge3b d4d2639ad94b0211839461226eb57a5e185829e5c4a9783c2da9f0a3da032bf5 hoge3b
良いですね。
4 MB、9 MB、11 MB 全てダウンロードすることが出来ました。
Lambda のタイムアウトがデフォルト 3 秒だと足りない場合があるのでそこだけ気をつけてください。
API Gateway + Lambda レスポンスストリーミング + S3
最後に Lambda レスポンスストリーミング + S3 の前段に更に API Gateway を配置しましょう。
次のような構成になります。
そもそも API Gateway で Lambda レスポンスストリーミングを受けれるのかという点はあるのですが、公式ドキュメントによるといけそうです。
この構成の場合、デフォルトレスポンスの Lambda の場合だと API Gateway (REST) のペイロードサイズ上限 10 MB の前に 6 MB の壁が問題になっていましたが、果たして。
なお、次のように Lambda 統合ではなく HTTP プロキシ統合を使っています。
% curl https://nbnhq77404.execute-api.ap-northeast-1.amazonaws.com/hoge/lambda/hoge1 -o hoge1c % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 4096k 100 4096k 0 0 2383k 0 0:00:01 0:00:01 --:--:-- 2391k % curl https://nbnhq77404.execute-api.ap-northeast-1.amazonaws.com/hoge/lambda/hoge2 -o hoge2c % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 9216k 100 9216k 0 0 2647k 0 0:00:03 0:00:03 --:--:-- 2652k % curl https://nbnhq77404.execute-api.ap-northeast-1.amazonaws.com/hoge/lambda/hoge3 -o hoge3c % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 36 100 36 0 0 14 0 0:00:02 0:00:02 --:--:-- 14 % shasum -a 256 hoge1a bb9f8df61474d25e71fa00722318cd387396ca1736605e1248821cc0de3d3af8 hoge1a % shasum -a 256 hoge1c bb9f8df61474d25e71fa00722318cd387396ca1736605e1248821cc0de3d3af8 hoge1c % shasum -a 256 hoge2a d2ee4703cd9698945ca7b9fe1689ea3095597eac1a0afd8dba00cac7894fdc43 hoge2a % shasum -a 256 hoge2c d2ee4703cd9698945ca7b9fe1689ea3095597eac1a0afd8dba00cac7894fdc43 hoge2c % shasum -a 256 hoge3a d4d2639ad94b0211839461226eb57a5e185829e5c4a9783c2da9f0a3da032bf5 hoge3a % shasum -a 256 hoge3c 660f19c09a36ca1620054261590b73df388b95892469ff17c1caf4e50376aa02 hoge3c % curl https://nbnhq77404.execute-api.ap-northeast-1.amazonaws.com/hoge/lambda/hoge3 -i HTTP/2 500 date: Mon, 24 Apr 2023 13:23:50 GMT content-type: application/json content-length: 36 x-amzn-requestid: f03ceda8-663b-4f9e-9fe1-504696fc99e8 x-amzn-errortype: InternalServerErrorException x-amz-apigw-id: D4ljvHrAtjMFfOw= {"message": "Internal server error"}
良いですね。
10 MB 以上は取得出来ていないですが、API Gateway + Lambda でも 6 MB 以上のレスポンスを生成することが出来ました。
余談;サイズ 20 MB 以上でもいけるっぽい?
この Lambda レスポンスストリーミング、ソフトリミットでデフォルトは最大 20 MB と公式ドキュメントには記述されていました。
Response stream payloads have a soft limit of 20 MB as compared to the 6 MB limit for buffered responses.
そこで 30 MB のオブジェクトで試してみました。
% dd if=/dev/zero of=hoge5 bs=1M count=30 30+0 records in 30+0 records out 31457280 bytes transferred in 0.022999 secs (1367767294 bytes/sec) % aws s3 cp hoge5 s3://iwasa-hoge-public-bucket/hoge0424/ upload: ./hoge5 to s3://iwasa-hoge-public-bucket/hoge0424/hoge5 % curl http://iwasa-hoge-public-bucket.s3-website-ap-northeast-1.amazonaws.com/hoge0424/hoge5 -o hoge5a % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 30.0M 100 30.0M 0 0 6635k 0 0:00:04 0:00:04 --:--:-- 6953k % curl https://rn3cg3rnzukafz7jisje7ysbay0wtdjv.lambda-url.ap-northeast-1.on.aws/hoge5 -o hoge5b % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 30.0M 0 30.0M 0 0 2443k 0 --:--:-- 0:00:12 --:--:-- 2052k % ls -lh total 123568 -rw-r--r-- 1 iwasa.takahito staff 30M Apr 24 22:40 hoge5a -rw-r--r-- 1 iwasa.takahito staff 30M Apr 24 22:41 hoge5b % shasum -a 256 hoge5a 75c91b29d5522c8a97c779e50bc33f11e07ed37b2baa31c8c727016e92915c1d hoge5a % shasum -a 256 hoge5b 75c91b29d5522c8a97c779e50bc33f11e07ed37b2baa31c8c727016e92915c1d hoge5b
あれ?30 MB でもダウンロード出来ていますね。
サービスクォータなどから上限の確認が出来なかったのですが、公式ドキュメントに記述の 20 MB の壁についてはもう少し調べる必要がありそうです。
ストリームの中で一度の送信で返すサイズ上限ということだろうか...。
さいごに
本日は AWS Lambda のレスポンスストリーミングを使って API Gateway + Lambda 構成で 10 MB のオブジェクトを生成してみました。
今まで API Gateway (REST) + Lambda で 6 MB の壁があったと思いますが、レスポンスストリーミングを使うことで API Gateway の上限までレスポンスを生成することが出来ました。
6 MB を 10 MB まで拡張するためにしては少し修正が大掛かりな気がしており限られたシーンでの利用にはなるかもしれないですが、出来るということだけでも覚えておくと良さそうです。